package org.acghub.config;

import org.apache.commons.lang3.StringUtils;

import java.util.Collection;
import java.util.Map;

/**
 * @Desc
 * @Author miyuki4j
 * @Date 2025/7/24/星期四 13:51
 * @Version 1.0
 */
public interface Type {

    String name();

    void parse(TableField field, String type, String delimiters) throws TypeParseException;

    String javaInterface();

    String javaImplementation();

    String javaDeclaration();

    String defaultValue();

    //实例化数据
    <T> T instance(String value, String delimiters) throws TypeInstanceException;

    // 导出验证数据
    default String exportVerify(String value, String delimiters) throws DataVerifyException {
        return value;
    }

    interface ContainerType extends Type {
        @Override
        default String defaultValue() {
            return "new " + javaImplementation() + "<>()";
        }
    }


    interface SimpleType<T> extends Type {

        @Override
        default void parse(TableField field, String type, String delimiters) throws TypeParseException {
            if (!name().equals(type)) {
                throw new TypeParseException("Invalid type " + type + " for " + name());
            }
        }

        @Override
        default String javaImplementation() {
            return javaInterface();
        }

        @Override
        default String javaDeclaration() {
            return javaInterface();
        }

        @Override
        T instance(String value, String delimiters) throws TypeInstanceException;
    }


    abstract class CollectionType<C extends Collection<?>> implements ContainerType {
        protected Type valueType;

        public final Type valueType() {
            return valueType;
        }

        @Override
        public void parse(TableField field, String type, String delimiters) throws TypeParseException {
            int len = name().length();
            String token = type.substring(len + 1);
            token = token.substring(0, token.length() - 1);
            if (StringUtils.length(delimiters) < 1) {
                throw new TypeParseException("bad delimiters \"" + delimiters + "\"");
            }
            valueType = TypeFactory.parseUnsafe(field, token, delimiters.substring(1));
        }

        @Override
        public String javaDeclaration() {
            return javaInterface() + "<" + valueType().javaDeclaration() + ">";
        }

        @Override
        public C instance(String value, String delimiters) throws TypeInstanceException {
            try {
                C collection = newCollection();
                String delimiter = org.acghub.config.StringUtils.getRegex(String.valueOf(delimiters.charAt(0)));
                String remainDelimiter = delimiters.substring(1);
                String[] values = value.split(delimiter);
                for (String val : values) {
                    collection.add(valueType.instance(val, remainDelimiter));
                }
                return collection;
            } catch (Exception e) {
                throw new TypeInstanceException(String.format("parse %s value:%s", name(), value), e);
            }
        }

        protected abstract C newCollection();
    }

    abstract class MapType<M extends Map<?, ?>> implements ContainerType {

        protected Type keyType;
        protected Type valueType;

        public final Type keyType() {
            return keyType;
        }

        public final Type valueType() {
            return valueType;
        }

        @Override
        public String javaInterface() {
            return "java.util.Map";
        }

        @Override
        public String javaDeclaration() {
            return javaInterface() + "<" + keyType().javaDeclaration() + ", " + valueType().javaDeclaration() + ">";
        }

        @Override
        public void parse(TableField field, String type, String delimiters) throws TypeParseException {
            int len = name().length();
            String token = type.substring(len + 1);
            token = token.substring(0, token.length() - 1);

            if (StringUtils.length(delimiters) < 2) {
                throw new TypeParseException("bad delimiters \"" + delimiters + "\"");
            }
            String[] kvTypeStrArr = token.split(",");
            if (kvTypeStrArr.length != 2) {
                throw new TypeParseException("bad type \"" + token + "\"");
            }
            delimiters = delimiters.substring(2);
            keyType = TypeFactory.parseUnsafe(field, StringUtils.trim(kvTypeStrArr[0]), delimiters);
            valueType = TypeFactory.parseUnsafe(field, StringUtils.trim(kvTypeStrArr[1]), delimiters);
        }

        @Override
        public M instance(String value, String delimiters) throws TypeInstanceException {
            try {
                M map = newMap();
                String firstDelimiter = org.acghub.config.StringUtils.getRegex(String.valueOf(delimiters.charAt(0)));
                String secondDelimiter = org.acghub.config.StringUtils.getRegex(String.valueOf(delimiters.charAt(1)));
                String remainDelimiter = delimiters.substring(2);
                String[] kvsArr = value.split(firstDelimiter);
                for (String kv : kvsArr) {
                    String[] kvArr = kv.split(secondDelimiter);
                    String key = kvArr[0];
                    String val = kvArr[1];
                    map.put(keyType.instance(key, remainDelimiter), valueType.instance(val, remainDelimiter));
                }
                return map;
            } catch (Exception e) {
                throw new TypeInstanceException(String.format("parse %s value:%s", name(), value), e);
            }
        }

        protected abstract M newMap();
    }
}
